/*
 * fscan.c
 *
 *  Created on: 11/09/2011
 *      Author: utn_so
 */


#include "fscan.h"



void trace_fscan(ptrColaParam *pedInic,ptrColaParam *pedFin,parametros aux)
{
	int i;
	int v[5];
	colaParam auxiliar;
	parsearTrace_f(aux.data,v);

	auxiliar.codigo = 7;
	auxiliar.flag = 0;
	auxiliar.socket = aux.cliente;
	auxiliar.sem = aux.semaforo;
	auxiliar.sgte = NULL;

	for(i=0;i<5;i++){
		if(v[i]>-1 && (v[i]< pista*sector)){
			auxiliar.SectorLogico = v[i];
			down(mutex2);
			agregarElemento_fscan(&pedAcum,auxiliar,'F');
			up(mutex2);
		}
	}


}

void calcularTiempos_fscan()
{
	int cambiaste = 0; //no cambio
	colaParam valorImprimir;
	if(pedInic==NULL){
		pedInic=pedFin;
		pedFin=NULL;
		sentidoBrazo=sentidoOpuesto_fscan(sentidoBrazo);
		cambiaste = 1;
	}

	if(pedInic != NULL){
		if(cambiaste==1){
			alExtremo(sentidoBrazo,valorImprimir.socket, valorImprimir.sem);
			sentidoBrazo=sentidoOpuesto_fscan(sentidoBrazo);
		}
		valorImprimir=buscar_fscan(pedInic,sentidoBrazo);
		imprimirResultados_fscan(valorImprimir);
	}


}

void agregarElemento_fscan(ptrColaParam* lista,colaParam aux, char sentido)
{
	ptrColaParam ptrAnterior;
	ptrColaParam ptrActual;
	ptrColaParam ptrNuevo;

	ptrNuevo = malloc(sizeof(colaParam));
	ptrNuevo->SectorLogico = aux.SectorLogico;
	memcpy(ptrNuevo->buffer,aux.buffer,512);
	ptrNuevo->codigo = aux.codigo;
	ptrNuevo->flag = aux.flag;
	ptrNuevo->sem = aux.sem;
	ptrNuevo->sgte = NULL;
	ptrNuevo->socket = aux.socket;
	if(flagLog==1 && (aux.codigo!= 6 || aux.codigo!=7) && sentido != 'F'){
		if(aux.codigo == 3 || aux.codigo == 4)log_info(log, "thread-principal", "Message info: llego pedido: escritura sector: %d\n", aux.SectorLogico);
		if(aux.codigo == 1 || aux.codigo == 2)log_info(log, "thread-principal", "Message info: llego pedido: lectura sector: %d\n", aux.SectorLogico);
	}
	ptrAnterior = NULL;
		ptrActual = *lista;
		if(sentido=='U'){
			while(ptrActual != NULL && (aux.SectorLogico >= ptrActual->SectorLogico)){
				ptrAnterior = ptrActual;
				ptrActual = ptrActual->sgte;
			}
		}
		if(sentido=='D'){
			while(ptrActual != NULL && (aux.SectorLogico <= ptrActual->SectorLogico)){
				ptrAnterior = ptrActual;
				ptrActual = ptrActual->sgte;
						}
		}
		if(sentido=='F'){
			while(ptrActual != NULL){
				ptrAnterior = ptrActual;
				ptrActual = ptrActual->sgte;
			}
		}

		if(ptrAnterior == NULL){
			ptrNuevo->sgte= *lista;
			*lista=ptrNuevo;
		}
		else{
			ptrAnterior->sgte=ptrNuevo;
			ptrNuevo->sgte=ptrActual;
		}
}





int imprimirResultados_fscan(colaParam ptrS) {


	int contadorPista,contadorSector,num;
	float leida;

	int cabezal_fPista = cabezal_f.SectorLogico/sector;
	int cabezal_fSector = cabezal_f.SectorLogico%sector;
	int tempSector,tempPista;

	NIPC paquete4;
	char* bufferNIPC4;
	char mensaje[1024];

	num = 0;
	contadorPista=0;
	contadorSector=0;

	if(ptrS.flag <=5 && ptrS.flag >= 2 && flagLog ==1)loguearLista_f();
	tempSector = (ptrS.SectorLogico)%sector;
	tempPista = (ptrS.SectorLogico)/sector;
	memset(mensaje,0,1024);
	sprintf(mensaje, "Posicion actual: %d:%d\nSector solicitado: %d:%d\nSectores leidos: ", cabezal_fPista, cabezal_fSector,tempPista,tempSector);
	if(ptrS.flag == 0){
	cargarEstructura(&paquete4,1,mensaje);
	bufferNIPC4 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
	serializar_NIPC(paquete4,bufferNIPC4);
	if(ptrS.sem!=-99) down(ptrS.sem);
	enviarNIPC(bufferNIPC4,paquete4.payloadLength+3,ptrS.socket);
	free(paquete4.mensaje);
	memset(mensaje,0,1024);
	}

	if(ptrS.flag <=5 && ptrS.flag >= 2 && flagLog ==1)log_debug(log, "thread-eliminar", "Message debug: %s", mensaje);//LOGEEAR

	memset(mensaje,0,1024);
	char concatenarDatos[50];
	memset(concatenarDatos,0,50);
	int cont=0;

	while(tempPista != cabezal_fPista){

			if(cont == 50){
				sprintf(concatenarDatos, "%d:%d ",cabezal_fPista,cabezal_fSector);
				strcat(mensaje,concatenarDatos);
				if(ptrS.flag == 0){
				cargarEstructura(&paquete4,1,mensaje);
				bufferNIPC4 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
				serializar_NIPC(paquete4,bufferNIPC4);
				if(ptrS.sem!=-99) down(ptrS.sem);
				enviarNIPC(bufferNIPC4,paquete4.payloadLength+3,ptrS.socket);
				free(paquete4.mensaje);
				cont =0;
				}
				if(ptrS.flag <=5 && ptrS.flag >= 2 && flagLog==1){
					pthread_mutex_lock(&log->mutex);
					if ( log->file != NULL ) {
						fprintf(log->file, "%s", mensaje);
						fflush(log->file);
					}
					pthread_mutex_unlock(&log->mutex);//LOGEEAR
				}

				memset(mensaje,0,1024);
			}

			else {
				sprintf(concatenarDatos, "%d:%d ",cabezal_fPista,cabezal_fSector);
				strcat(mensaje,concatenarDatos);
				cont++;

			}
			memset(concatenarDatos,0,50);
			if(cabezal_fPista < tempPista) {
				cabezal_fPista++; cabezal_f.SectorLogico += sector;
			}

			else {
				cabezal_fPista--; cabezal_f.SectorLogico -= sector;
			}
			contadorPista++;

			}

	if(ptrS.flag == 0){
	cargarEstructura(&paquete4,2,mensaje);
	bufferNIPC4 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
	serializar_NIPC(paquete4,bufferNIPC4);
	if(ptrS.sem!=-99) down(ptrS.sem);
	enviarNIPC(bufferNIPC4,paquete4.payloadLength+3,ptrS.socket);
	free(paquete4.mensaje);
	memset(mensaje,0,1024);
	}
	if(ptrS.flag <=5 && ptrS.flag >= 2 && flagLog==1){
		pthread_mutex_lock(&log->mutex);
		if ( log->file != NULL ) {
			fprintf(log->file, "%s", mensaje);
			fflush(log->file);
		}
		pthread_mutex_unlock(&log->mutex);//LOGEEAR
	}
	cont = 0;


	while(tempSector != cabezal_fSector){

		if(cont == 50){
			sprintf(concatenarDatos, "%d:%d ",cabezal_fPista,cabezal_fSector);
			strcat(mensaje,concatenarDatos);
			if(ptrS.flag == 0){
			cargarEstructura(&paquete4,1,mensaje);
			bufferNIPC4 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
			serializar_NIPC(paquete4,bufferNIPC4);
			if(ptrS.sem!=-99) down(ptrS.sem);
			enviarNIPC(bufferNIPC4,paquete4.payloadLength+3,ptrS.socket);
			free(paquete4.mensaje);
			cont =0;}
			if(ptrS.flag <=5 && ptrS.flag >= 2 && flagLog==1){
				pthread_mutex_lock(&log->mutex);
				if ( log->file != NULL ) {
					fprintf(log->file, "%s", mensaje);
					fflush(log->file);
				}
				pthread_mutex_unlock(&log->mutex);//LOGEEAR
			}

			memset(mensaje,0,1024);
		}

		else {
			sprintf(concatenarDatos, "%d:%d ",cabezal_fPista,cabezal_fSector);
			strcat(mensaje,concatenarDatos);
			cont++;

			};
		memset(concatenarDatos,0,50);

				if(cabezal_fSector != tempSector) {
					cabezal_fSector++;cabezal_f.SectorLogico++;
					if(((cabezal_fSector)%(sector))==0){
						cabezal_fSector-=sector;
						cabezal_f.SectorLogico-=sector;
					}
				}

				contadorSector++;

				}

				if((cabezal_fSector+1%(sector))==0){
					cabezal_fSector-=sector-1;
					cabezal_f.SectorLogico-=sector-1;
				}

				contadorSector++;

				sprintf(concatenarDatos, "%d:%d ",cabezal_fPista,cabezal_fSector);
				strcat(mensaje,concatenarDatos);


				leida = (float)60*sector/rpm;
				colaParam proximoSector;
				down(mutexFscan);
				quitar_f(&pedInic,ptrS);
				up(mutexFscan);
				proximoSector = buscar_fscan(pedInic,sentidoBrazo);



				sprintf(concatenarDatos, "\nTiempo consumido: %f milisegundos\n ",(float)contadorSector*1000*(float)60*sector/rpm +(contadorPista*tiempoEntrePistas)+ leida);
				strcat(mensaje,concatenarDatos);
				if(proximoSector.SectorLogico != -99){
				memset(concatenarDatos,0,50);
				sprintf(concatenarDatos,"Proximo sector: %d:%d\n",proximoSector.SectorLogico/sector, proximoSector.SectorLogico%sector);
				strcat(mensaje,concatenarDatos);
				}
				if(ptrS.flag == 0){
				cargarEstructura(&paquete4,1,mensaje);
				bufferNIPC4 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
				serializar_NIPC(paquete4,bufferNIPC4);
				if(ptrS.sem!=-99) down(ptrS.sem);
				enviarNIPC(bufferNIPC4,paquete4.payloadLength+3,ptrS.socket);
				free(paquete4.mensaje);}
				if(ptrS.flag <=5 && ptrS.flag >= 2 && flagLog==1){
					pthread_mutex_lock(&log->mutex);
					if ( log->file != NULL ) {
						fprintf(log->file, "%s", mensaje);
						fflush(log->file);
					}
					pthread_mutex_unlock(&log->mutex);//LOGEEAR
				}
				memset(mensaje,0,1024);

				if( ((cabezal_fSector+1) % sector) == 0)  cabezal_f.SectorLogico -= sector ;
					cabezal_f.SectorLogico++;

				if(ptrS.flag == 0){
				cargarEstructura(&paquete4,9,mensaje);
				bufferNIPC4 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
				serializar_NIPC(paquete4,bufferNIPC4);
				if(ptrS.sem!=-99) down(ptrS.sem);
				enviarNIPC(bufferNIPC4,paquete4.payloadLength+3,ptrS.socket);
				free(paquete4.mensaje);
				free(bufferNIPC4);
				}
				if(ptrS.flag == 1){
					comparacionClean++;
					escribirArchivoDisco(ptrS.SectorLogico,ptrS.buffer);
					if(comparacionClean == contadorClean){
						char * bufferNIPC7;
						memset(mensaje,0,1024);
						sprintf(mensaje,"Fin del CLEAN realizado exitosamente.\n");
						cargarEstructura(&paquete4,1,mensaje);
						bufferNIPC7 = malloc(sizeof(char)* paquete4.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
						serializar_NIPC(paquete4,bufferNIPC7);
						if(ptrS.sem!=-99) down(ptrS.sem);
						enviarNIPC(bufferNIPC7,paquete4.payloadLength+3,ptrS.socket);
						free(paquete4.mensaje);
						free(bufferNIPC7);
					}
				}
				if(ptrS.flag == 4 || ptrS.flag == 5){
					leerArchivoDisco(ptrS.SectorLogico,ptrS.buffer);
						NIPC paquete59;
						char* bufferNIPC59;

						memset(mensaje,0,1024);
						memcpy(mensaje,ptrS.buffer,512);
						memcpy(mensaje+512,&ptrS.SectorLogico,sizeof(uint32_t));
						uint16_t tamanio;
						if(ptrS.flag == 4)	paquete59.payloadDescriptor = (uint8_t)1;
						if(ptrS.flag == 5)	paquete59.payloadDescriptor = (uint8_t)2;
						paquete59.payloadLength = (uint16_t)512+4;
						tamanio = paquete59.payloadLength;
						paquete59.mensaje = malloc(tamanio);
						memset(paquete59.mensaje,0,tamanio);

						memcpy(paquete59.mensaje,mensaje,512+4);
						bufferNIPC59 = malloc(paquete59.payloadLength + sizeof(uint8_t) + sizeof(uint16_t));
						serializar_NIPC(paquete59,bufferNIPC59);
					//	printf("leiSector %d-%d-%s\n",ptrS.SectorLogico,ptrS.flag,ptrS.buffer);

					//	enviarNIPC(bufferNIPC59,paquete59.payloadLength+3,ptrS.socket);
						uint8_t tipo2;
						memcpy(&tipo2,bufferNIPC59,sizeof(uint8_t));
						if(tipo2==0){
							printf("%d\n",tipo2);
						}
						memset(mensaje,0,1024);
						free(paquete59.mensaje);
						free(bufferNIPC59);
				}

				if(ptrS.flag == 2 || ptrS.flag == 3){
					uint32_t verifica;
					verifica = escribirArchivoDisco(ptrS.SectorLogico,ptrS.buffer);
					printf("escribi sector: %d.\n",ptrS.SectorLogico);
					if(ptrS.flag != 3){//no respondo si es escritura duplicada
						NIPC paquete57;
						char* bufferNIPC57;

						memset(mensaje,0,1024);
						memcpy(mensaje,&verifica,sizeof(uint32_t));
						memcpy(mensaje+sizeof(uint32_t),&ptrS.SectorLogico,sizeof(uint32_t));
						uint16_t tamanio;
						paquete57.payloadLength = (uint16_t)4 + sizeof(uint32_t)*2;
						tamanio = paquete57.payloadLength;
						paquete57.mensaje = malloc(sizeof(uint32_t)*2);
						memset(paquete57.mensaje,0,tamanio);

						memcpy(paquete57.mensaje,mensaje,sizeof(uint32_t)*2);
						bufferNIPC57 = malloc(sizeof(uint32_t)* paquete57.payloadLength + sizeof(uint8_t) + sizeof(uint16_t) );
						paquete57.payloadDescriptor = (uint8_t)3;
						serializar_NIPC(paquete57,bufferNIPC57);
						enviarDatosA(bufferNIPC57,paquete57.payloadLength+3,ptrS.socket);

						memset(mensaje,0,1024);
						free(paquete57.mensaje);
						free(bufferNIPC57);
					}
				}
				return 0;

}



void selecCola_fscan(ptrColaParam *pedInic,ptrColaParam *pedFin,colaParam aux, char sentido){

	char sentidoOpuestoBrazo;

	if ((sentido=='U' && cabezal_f.SectorLogico/pista <= aux.SectorLogico/pista) || (sentido=='D' && cabezal_f.SectorLogico/pista >= aux.SectorLogico/pista)){
		down(mutexFscan);
		agregarElemento_fscan(&(*pedInic),aux,sentido);
		up(mutexFscan);
	}
	else{
		sentidoOpuestoBrazo=sentidoOpuesto_fscan(sentido);
		down(mutexFscan);
		agregarElemento_fscan(&(*pedFin),aux,sentidoOpuestoBrazo);
		up(mutexFscan);
	}
}


char sentidoOpuesto_fscan(char sentido){

	switch(sentido){
			case 'U': return 'D';
			case 'D': return 'U';
	}
}

void alExtremo(char sentido, int fd ,int sem){
	colaParam ptrMaxMin;
	colaParam proximoSector;
	proximoSector = buscar_fscan(pedInic,sentidoBrazo);
	if(proximoSector.flag != 0){
		ptrMaxMin.codigo = 7;
		ptrMaxMin.flag = 7;
	}

	else {
		ptrMaxMin.codigo = 8;
		ptrMaxMin.flag = 8;

	}
	if(sentido=='U'){
		printf("voy al tope del disco\n");
		ptrMaxMin.SectorLogico=pista*sector-1;
		}
		if(sentidoBrazo=='D'){
			printf("voy al inicio del disco\n");
			ptrMaxMin.SectorLogico=0;
		}
		imprimirResultados_fscan(ptrMaxMin);
}

colaParam buscar_fscan(ptrColaParam lista,char sentido){

	ptrColaParam ptraux;
	int pistaBuscada;
	colaParam elementoRetorno;
	ptraux=lista;
	if(ptraux != NULL){
			pistaBuscada = ptraux->SectorLogico/sector;
			while(ptraux!=NULL && pistaBuscada == ptraux->SectorLogico/sector && ptraux->SectorLogico%sector < cabezal_f.SectorLogico%sector){
				ptraux=ptraux->sgte;
			}
			if(ptraux == NULL || pistaBuscada != ptraux->SectorLogico/sector){
				elementoRetorno.SectorLogico=lista->SectorLogico;
				elementoRetorno.flag= lista->flag;
				elementoRetorno.codigo = lista->codigo;
				elementoRetorno.socket = lista->socket;
				memcpy(elementoRetorno.buffer,lista->buffer,512);
				elementoRetorno.sgte = NULL;
				elementoRetorno.sem = lista->sem;
				return elementoRetorno;

			}
			else {
				elementoRetorno.SectorLogico = ptraux->SectorLogico;
				elementoRetorno.flag = ptraux->flag;
				elementoRetorno.codigo = ptraux->codigo;
				elementoRetorno.socket = lista->socket;
				memcpy(elementoRetorno.buffer,ptraux->buffer,512);
				elementoRetorno.sgte = NULL;
				elementoRetorno.sem = lista->sem;
				return elementoRetorno;

			}
	}
	else {
		elementoRetorno.SectorLogico = -99;
		elementoRetorno.flag = -99;
		elementoRetorno.codigo = -99;
		elementoRetorno.sgte = NULL;
		elementoRetorno.socket = -99;
		elementoRetorno.sem = -99;
		return elementoRetorno;
	}
}

int quitar_f(ptrColaParam *lista,colaParam datoEliminar)
{

	ptrColaParam ptrAnterior;
	ptrColaParam ptrActual;
	ptrColaParam tempPtr;
		if((*lista)->SectorLogico == datoEliminar.SectorLogico && (*lista)->flag == datoEliminar.flag){
			tempPtr = *lista;
			(*lista) = (*lista)->sgte;
			free(tempPtr);
		}
		else{
			ptrAnterior = (*lista);
			ptrActual = (*lista)->sgte;

			while(ptrActual != NULL && ptrActual->SectorLogico != datoEliminar.SectorLogico){
				if(ptrActual->flag == datoEliminar.flag && ptrActual->SectorLogico == datoEliminar.SectorLogico){
				break;
				}
				else{
					ptrAnterior = ptrActual;
					ptrActual = ptrActual->sgte;
				}
			}
		if(ptrActual != NULL){
			tempPtr = ptrActual;
			ptrAnterior->sgte = ptrActual->sgte;
			free(tempPtr);
		}

		}
	return 0;
}

int imprimir_f(ptrParPS_f ptrActual){    //funcion que corrobora como se metio la lista

	ptrParPS_f ptrAux;

	ptrAux=ptrActual;
	if(ptrAux==NULL) {
		printf("lista vacia\n");
		//ACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	}
	else{
		while(ptrAux != NULL){
				printf("%d - ",ptrAux->SectorLogico);
				ptrAux= ptrAux->ptrSgte;
			}
		printf("\n");
	}
	return 0;
}

int parsearTrace_f(char * c, int* v)
{
	char* vector[5+1] = {"-1","-1","-1","-1","-1","-1"};
	int i=0,j=0;
	char* ptrTok;

	for(i=0;i<5;i++) v[i]=-1;
	strtok(c," ");
	for(i=0;i<5;i++){
			ptrTok = strtok(NULL," ");
			if (ptrTok != NULL){
				vector[i] = ptrTok;
					if (isdigit(*vector[i]) != 0){
						v[j] = atoi(vector[i]);
						j++;
							}
					else printf("se ha introducido un caracter no valido, "
							"no se tendra en cuenta en la evaluacion.\n");
			}
		}
	return 0;
}


int descargarAcumulada(ptrColaParam *ptrLstAcum)
{
	ptrColaParam ptrActual;
	colaParam aux;
	if(*ptrLstAcum!=NULL){
		down(mutex2);
		while((*ptrLstAcum) != NULL){
			aux.SectorLogico = (*ptrLstAcum)->SectorLogico;
			memcpy(aux.buffer ,(*ptrLstAcum)->buffer,512);
			aux.codigo = (*ptrLstAcum)->codigo;
			aux.flag = (*ptrLstAcum)->flag;
			aux.sem = (*ptrLstAcum)->sem;
			aux.socket = (*ptrLstAcum)->socket;
			aux.sgte = NULL;
			selecCola_fscan(&pedInic,&pedFin,aux,sentidoBrazo);
			ptrActual = (*ptrLstAcum);
			(*ptrLstAcum) = (*ptrLstAcum)->sgte;
			free(ptrActual);
		}
		(*ptrLstAcum) = NULL;
		up(mutex2);
	}
	return 0;
}

int loguearLista_f(){    //funcion que corrobora como se metio la lista

	ptrColaParam ptrAux;
	int contadorPedidos=0;
	ptrAux=pedInic;
	if(ptrAux==NULL) {
	}
	else{
		if ( log->file != NULL ) {
			log_debug(log, "thread-eliminar", "Message debug: %s", "Cola Pedidos: [");
			}
		while(ptrAux != NULL){
			if(ptrAux->flag <=5 && ptrAux->flag >= 2){
				pthread_mutex_lock(&log->mutex);
				fprintf(log->file, "%d:%d  ", ptrAux->SectorLogico/pista,ptrAux->SectorLogico%pista);
				fflush(log->file);
				pthread_mutex_unlock(&log->mutex);
				contadorPedidos++;
			}
				ptrAux= ptrAux->sgte;
		}
	}
	ptrAux=pedFin;
	if(ptrAux==NULL) {
		}
		else{
			while(ptrAux != NULL){
				if(ptrAux->flag <=5 && ptrAux->flag >= 2){
					pthread_mutex_lock(&log->mutex);
					fprintf(log->file, "%d:%d  ", ptrAux->SectorLogico/pista,ptrAux->SectorLogico%pista);
					fflush(log->file);
					pthread_mutex_unlock(&log->mutex);
					contadorPedidos++;
				}
					ptrAux= ptrAux->sgte;
			}
		}
		pthread_mutex_lock(&log->mutex);
		fprintf(log->file, "] Tamaño: %d\n",contadorPedidos);
		fflush(log->file);
		pthread_mutex_unlock(&log->mutex);

	return 0;
}
